package com.dj.controller;

import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import com.dj.service.PatientService;
import com.dj.util.CrudOperationUtil;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.Meta;
import org.hl7.fhir.dstu3.model.Patient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @author cyf
 * @description 患者
 * @create 2018-06-27 10:54
 **/

@Controller
public class PatientController {

    private static final Logger logger = LoggerFactory.getLogger(PatientController.class);

    @Autowired
    private PatientService patientService;


    /**
     * 创建
     *
     * @param patient
     * @return
     */
    @Create
    @Transactional
    public MethodOutcome create(@ResourceParam Patient patient) {
        long startTime = System.currentTimeMillis();
        logger.info("Patient create start!!!");

        //判断 identifier
        if (patient.getIdentifierFirstRep().isEmpty()) {
            throw new UnprocessableEntityException("No identifier supplied");
        }
        //执行 create
        IdType idType = patientService.savePatient(patient);
        return CrudOperationUtil.getMethodOutcome(idType, startTime);
        //return CrudOperationUtil.create(thePatient, patientService::savePatient);
    }

    /**
     * 更新
     *
     * @param theId
     * @param patient
     * @return
     */
    @Update
    @Transactional
    public MethodOutcome update(@IdParam IdType theId, @ResourceParam Patient patient) {
        long startTime = System.currentTimeMillis();
        logger.info("Patient update start!!!, theId is {}" , theId);
        String id = theId.getIdPart();
        IdType idType = patientService.updatePatient(id, patient);
        return CrudOperationUtil.getMethodOutcome(idType, startTime);
        //return CrudOperationUtil.update(theId,thePatient,(id, patient) -> patientService.updatePatient(id,patient));
    }

    /**
     * id读取患者/历史
     *
     * @param theId
     * @return
     */
    @Read(version = true)
    public Patient getByIdOrVersion(@IdParam IdType theId) {

        logger.info("Patient getByIdOrVersion start!!!, theId={}", theId);
        String id = theId.getIdPart();
        Patient patient = new Patient();
        Meta meta = new Meta();

        if (theId.hasVersionIdPart()) {
            logger.info("query history!");
            //历史记录
            String version = theId.getVersionIdPart();
            Date date = patientService.getHistoryLastUpdatTime(id, version);
            if(date != null){
                meta.setLastUpdated(date);
                patient = patientService.getPatientByIdAndVersion(id, version);
            } else {
                logger.info("Error, This historical version does not exist, the version is {}",version);
            }
        } else {
            //当前记录
            logger.info("query the current record!");
            Date lastUpdatTime = patientService.getLastUpdatTime(id);
            meta.setLastUpdated(lastUpdatTime);
            patient = patientService.getPatientById(id);
        }
        //设置 meta LastUpdated
        if (!patient.isEmpty()) {
            patient.setMeta(meta);
        } else {
            patient = CrudOperationUtil.getQueryEmpty(patient,"Patient/"+id);
        }
        return patient;
        //return CrudOperationUtil.readOrVRead(theId,patientService::getPatientById,(id, version)-> patientService.getPatientByIdAndVersion(id,version));
    }

    /**
     * 查询所有历史记录
     *
     * @param theId
     * @return
     */
    @History(type = Patient.class)
    public List<Patient> getPatientHistory(@IdParam IdType theId) {
        logger.info("Patient getAllPatientHistory start!!!, theId={}", theId);
        String id = theId.getIdPart();
        return patientService.getAllPatientById(id);
    }

    /**
     * Patient.SP_NAME = name
     * name读取患者
     *
     * @param name
     * @return
     */
    @Search()
    public List<Patient> searchByName(@RequiredParam(name = Patient.SP_NAME) StringParam name) {
        logger.info("Patient searchByName start!!!, name={}", name);
        return patientService.getPatientByName(name);
    }

    /**
     * 删除
     *
     * @param theId
     * @return
     */
    @Delete(type = Patient.class)
    @Transactional
    public MethodOutcome delete(@IdParam IdType theId) {
        long startTime = System.currentTimeMillis();
        logger.info("Patient delete start!!!, theId={}", theId);
        return CrudOperationUtil.delete(theId, patientService::deletePatient, startTime);
    }


}
